import os
import re
import requests
import json
from enum import Enum, auto
from openai import OpenAI
from datetime import datetime
from mcp.server.fastmcp import FastMCP

# 加载 .env 文件（如果有）
from dotenv import load_dotenv
load_dotenv()

# 初始化MCP服务器
mcp = FastMCP("MyServer")


# 定义搜索枚举
class searchType(Enum):
    # 如何使用
    """
    用于定义search_by_google的搜索类型

        Use:
            searchType.Search.name ==> Search   名称
            searchType.Search.value ==> 1       值
        Suggestions:
            在使用的时候，建议将类型的name值转换为小写字母
    """

    Search = auto()
    Images = auto()
    Videos = auto()
    News = auto()


def ensure_chinese(
    text: str,
    *,
    allow_punctuation: bool = True,
    allow_numbers: bool = False,
    allow_arabic_numbers: bool = True,
    allow_space: bool = False,
) -> str:
    """
    验证字符串是否为中文

        Args:
            text: 要验证的字符串
            allow_punctuation: 是否允许中文标点（默认允许）
            allow_numbers: 是否允许中文数字（默认不允许）
            allow_arabic_numbers: 是否允许阿拉伯数字 0-9（默认允许）
            allow_space: 是否允许空格（默认不允许）

        Returns:
            原始字符串（验证通过时）

        Raises:
            ValueError: 如果包含非中文字符
    """
    pattern = r"^[\u4e00-\u9fa5"
    if allow_punctuation:
        pattern += r"，。！？；：“”‘’（）【】《》"
    if allow_numbers:
        pattern += r"〇零一二三四五六七八九十百千万亿"
    if allow_arabic_numbers:
        pattern += r"0-9"
    if allow_space:
        pattern += r" "
    pattern += r"]+$"

    if not re.fullmatch(pattern, text):
        raise ValueError(f"只允许输入中文{'和标点' if allow_punctuation else ''}")
    return text


@mcp.tool()
def search_by_google(type: str, query: str) -> str:
    """
    谷歌搜索工具

        Desc:通过该工具搜索query相关内容

        Args:
            type:搜索类型，需要在searchType中存在
                固定值有：Search | Images | Videos | News
                要求：必须严格按照上述固定值的枚举参数传递，不能为数值，只能为字符串。比如，出现搜索关键字 => "Search" 或者 出现新闻关键字 => "News"。
            query:搜索标题
                "请求标题目前限定为中文内容，不支持其他语言"
        Returns:

    """
    exists = type in {t.name for t in searchType}
    if not exists:
        raise ValueError("type不存在于searchType(Enum)!")
    sType = type.lower()

    url = f"https://google.serper.dev/{sType}"

    searchTitle = ensure_chinese(query)

    payload = json.dumps({"q": searchTitle})

    # 请求头
    headers = {
        "X-API-KEY": "1a046f50624dacc82f3cb545c51c4cc9ec4dda6f",    # your api key
        "Content-Type": "application/json",
    }

    response = requests.request("POST", url, headers=headers, data=payload)

    data_obj = json.loads(response.text)
    searchContent = []
    # 筛选出数据
    if sType == "search":
        searchContent = data_obj["organic"]
    else:
        searchContent = data_obj[f"{sType}"]

    # 转换为 mcp 要求工具函数返回的数据格式为一个有效的string
    result = json.dumps(searchContent)
    return result

@mcp.tool()
def sentiment_analysis(content: str,path:str) -> str:
    """
    情感分析工具：
    用于对搜索到的内容进行一个情感的分析，然后生成一个情感分析报告文件(.md)保存在本地，最后将文件的路径返回
        Args:
            content: 情感分析内容
            path: 传递过来的路径，必填值
        Returns:
            filepath:str  => 返回的是一个关于.md文件的路径
    """

    # 1、提示词
    sysPrompt = """
        作为情感分析专家，你将以第三人称视角分析输入的新闻/评论内容。处理流程：
        1. 原始输入 
            - JSON提取content字段/直接使用文本 
        2. 情感分析 
            - 识别关键词，判断积极/消极倾向，输出概率分布 
        3. 分层解析 
            - 表层分析（直接情感）
            - 深层分析（隐含意图/社会影响）
            - 矛盾点检测 
        4. 总结 
            - 关键发现/潜在影响/后续建议。(总结中的标题和正文应该分隔开)
        
        输出要求：
            不要出现无关分析内容 ！！！！！
            严格使用Markdown格式，##二级标题起，标题与正文间空行，禁止标题嵌入段落（需转义####为\\#\\#\\#\\#），概率数据用代码块包装。
            标题符号 #之间不应该有空格，比如三级标题 ## #这样就导致了原本的三级变成二级标题，且最前面加上了#号
            可以根据情绪适当在内容中添加emoji
    """
    userPrompt = f"""
    请对下面内容进行情感分析，并说明原因：\n\n
    {content}

    输出格式：
    ## xxx舆情分析报告，如25年全球局势新闻舆情分析报告  
    ---
    正文内容..... (500字以内的分析内容，有论点及论据)
    """
    # 2、获取模型配置
    model = os.getenv(
        "MODEL", "qwen2.5-vl-32b-instruct"
    )  # 没有获取到模型Id，则设置默认值qwen2.5-vl-32b-instruct
    base_url = os.getenv("BASE_URL")
    api_key = os.getenv("API_KEY")

    
    # 3、获取模型回复
    client = OpenAI(api_key=api_key, base_url=base_url)
    response = client.chat.completions.create(
        model=model,
        messages=[
            {"role": "system", "content": sysPrompt},
            {"role": "user", "content": userPrompt},
        ],
    )
    # print(response.choices[0].message.content)

    # 4、生成md情感分析报告
    # 4.1 获取md文件内容
    markdown = f"""
    {response.choices[0].message.content}
    """
    output_dir = "//sentiment_reports"
    # 4.2 创建目录及文件
    output_dir = path + output_dir
    os.makedirs(output_dir, exist_ok=True)
    filename = f"sentiment_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
    file_path = os.path.join(output_dir, filename)
    with open(file_path, "w", encoding="utf-8") as f:
        f.write(markdown)

    # 5、返回路径
    return file_path




@mcp.resource("greeting://{name}")
def get_greeting(name: str) -> str:
    """Get a personalized greeting"""
    return f"Hello, {name}!"

if __name__ == "__main__":
    mcp.run(transport='stdio')  # 本地标准输入输出(stdio) / sse
